package com.ruoyi.system.service.impl;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.constant.TaxConstants;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.http.HttpClientUtil;
import com.ruoyi.common.utils.sign.TAXSignatureUtil;
import com.ruoyi.system.domain.WaterMeter;
import com.ruoyi.system.domain.WaterMeterDatahistory;
import com.ruoyi.system.domain.WaterYcmeterDatahistory;
import com.ruoyi.system.domain.tax.*;
import com.ruoyi.system.mapper.WaterMeterDatahistoryMapper;
import com.ruoyi.system.service.IWaterMeterDatahistoryService;
import com.ruoyi.system.service.IWaterMeterService;
import com.ruoyi.system.service.IWaterYcmeterDatahistoryService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 抄表数据Service业务层处理
 *
 * @author ruoyi
 * @date 2025-09-16
 */
@Service
public class WaterMeterDatahistoryServiceImpl implements IWaterMeterDatahistoryService
{
    private static final Logger log = LoggerFactory.getLogger(WaterMeterDatahistoryServiceImpl.class);
    // 访问频率控制
    private final Map<String, Long> lastAccessTime = new HashMap<>();
    private static final long MIN_INTERVAL = 1000L / 6; // 每秒最多6次

    @Autowired
    private IWaterMeterService waterMeterService;
    @Autowired
    private WaterMeterDatahistoryMapper waterMeterDatahistoryMapper;

    @Autowired
    private IWaterYcmeterDatahistoryService historyService;

    @Autowired
    private TAXSignatureUtil signatureUtil;
    @Autowired
    private HttpClientUtil httpClientUtil;
    @Autowired
    private ObjectMapper objectMapper;

    /**
     * 查询抄表数据
     *
     * @param id 抄表数据主键
     * @return 抄表数据
     */
    @Override
    public WaterMeterDatahistory selectWaterMeterDatahistoryById(Long id)
    {
        return waterMeterDatahistoryMapper.selectWaterMeterDatahistoryById(id);
    }

    /**
     * 查询抄表数据列表
     *
     * @param waterMeterDatahistory 抄表数据
     * @return 抄表数据
     */
    @Override
    public List<WaterMeterDatahistory> selectWaterMeterDatahistoryList(WaterMeterDatahistory waterMeterDatahistory)
    {
        return waterMeterDatahistoryMapper.selectWaterMeterDatahistoryList(waterMeterDatahistory);
    }

    @Override
    public List<WaterMeterDatahistory> getUserDataHislist(String userid, Integer beginSize, Integer endSize) {
        return waterMeterDatahistoryMapper.getUserDataHislist(userid,beginSize,endSize);
    }

    /**
     * 新增抄表数据
     *
     * @param waterMeterDatahistory 抄表数据
     * @return 结果
     */
    @Override
    public int insertWaterMeterDatahistory(WaterMeterDatahistory waterMeterDatahistory)
    {
        waterMeterDatahistory.setCreateTime(DateUtils.getNowDate());
        int num = waterMeterDatahistoryMapper.insertWaterMeterDatahistory(waterMeterDatahistory);
        if(num>0){
            WaterMeter waterMeter = waterMeterService.selectWaterMeterByMeterNo(waterMeterDatahistory.getMeterNo());
            waterMeter.setInitialReading(waterMeterDatahistory.getLastReading());
            waterMeter.setCurrentReading(waterMeterDatahistory.getCurrentReading());
            waterMeter.setControlStatus("0");
            waterMeter.setFlux(waterMeterDatahistory.getFlowRate());
            waterMeter.setPressure(waterMeterDatahistory.getPressure());
            waterMeter.setReadDate(waterMeterDatahistory.getReadDate());
            waterMeterService.updateWaterMeter(waterMeter);
        }
        return num;
    }

    /**
     * 修改抄表数据
     *
     * @param waterMeterDatahistory 抄表数据
     * @return 结果
     */
    @Override
    public int updateWaterMeterDatahistory(WaterMeterDatahistory waterMeterDatahistory)
    {
        return waterMeterDatahistoryMapper.updateWaterMeterDatahistory(waterMeterDatahistory);
    }

    /**
     * 批量删除抄表数据
     *
     * @param ids 需要删除的抄表数据主键
     * @return 结果
     */
    @Override
    public int deleteWaterMeterDatahistoryByIds(Long[] ids)
    {
        return waterMeterDatahistoryMapper.deleteWaterMeterDatahistoryByIds(ids);
    }

    /**
     * 删除抄表数据信息
     *
     * @param id 抄表数据主键
     * @return 结果
     */
    @Override
    public int deleteWaterMeterDatahistoryById(Long id)
    {
        return waterMeterDatahistoryMapper.deleteWaterMeterDatahistoryById(id);
    }

    @Override
    public int syncWaterMeterData(WaterMeter waterMeter,String startTime) {
        List<DeviceQuery> queries = new ArrayList<>();
        DeviceQuery query1 = new DeviceQuery();
        query1.setFmaddress(waterMeter.getMeterNo());
        query1.setStarttime(startTime);
        query1.setNumber(10);
        queries.add(query1);
        BaseResponse<FluxPressureData> response = getFluxPressureData(queries);
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.HOUR, -6);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        String sTime = sdf.format(calendar.getTime());
        query1.setStarttime(sTime);
        query1.setNumber(150);
        queries.add(query1);
        BaseResponse<BatterySignalData> signalResponse = getBatterySignalData(queries);
        if (!"0".equals(response.getCode())) {
            log.error("获取水表{}流量压力数据失败: {}", waterMeter.getMeterNo(), response.getMessage());
            return 0;
        }
        if (response.getBody() == null || response.getBody().isEmpty()) {
            log.warn("水表{}流量压力数据为空", waterMeter.getMeterNo());
            return 0;
        }
        DeviceData<FluxPressureData> deviceData = response.getBody().get(0);
        DeviceData<BatterySignalData> signalDataDeviceData = signalResponse.getBody().get(0);
        if (!"0".equals(deviceData.getCode())) {
            return 0;
        }

        List<FluxPressureData> values = deviceData.getValues();
        List<BatterySignalData> values1 = signalDataDeviceData.getValues();
        if (values == null || values.isEmpty()) {
            return 0;
        }
        BatterySignalData signalData = new BatterySignalData();
        if (values1 == null || values1.isEmpty()) {
//            return 0;
        }else{
            signalData = values1.get(values1.size() - 1);
        }
        // 取最后一条（最新的一条）
//        FluxPressureData latestData = values.get(values.size() - 1);
        FluxPressureData latestData = values.get(0);
//        BatterySignalData signalData = values1.get(values1.size() - 1);
        WaterYcmeterDatahistory dataHistory = new WaterYcmeterDatahistory();
        dataHistory.setMeterNo(waterMeter.getMeterNo());
        dataHistory.setUserId(waterMeter.getUserId());
        dataHistory.setMeterType("0"); // 远传表
        dataHistory.setReadDate(latestData.getReadtime()); // 抄表时间
        dataHistory.setLastReading(Double.valueOf(waterMeter.getCurrentReading())); // 上次抄表数
        dataHistory.setCurrentReading(latestData.getTotalFlux()); // 累计流量
        dataHistory.setPlustotalflux(latestData.getPlusTotalFlux()); // 正向累计流量
        dataHistory.setReversedotalflux(latestData.getReverseTotalFlux()); // 反向累计流量
        dataHistory.setPressure(latestData.getPressure()); // 压力
        dataHistory.setFlowRate(latestData.getFlux()); // 瞬时流量
        dataHistory.setTension1(signalData.getTension1()); // 通讯电池电压
        dataHistory.setTension2(signalData.getTension2());  // 计量电池电压
        dataHistory.setSignalinten(signalData.getSignallnten()); // 信号强度
        historyService.insertWaterYcmeterDatahistory(dataHistory); // 添加历史数据
        /*for(FluxPressureData data:values){
            WaterYcmeterDatahistory dataHistory = new WaterYcmeterDatahistory();
            dataHistory.setMeterNo(waterMeter.getMeterNo());
            dataHistory.setUserId(waterMeter.getUserId());
            dataHistory.setMeterType("0"); // 远传表
            dataHistory.setReadDate(data.getReadtime()); // 抄表时间
            dataHistory.setCurrentReading(data.getTotalFlux()); // 累计流量
            dataHistory.setPlustotalflux(data.getPlusTotalFlux()); // 正向累计流量
            dataHistory.setReversedotalflux(data.getReverseTotalFlux()); // 反向累计流量
            dataHistory.setPressure(data.getPressure()); // 压力
            dataHistory.setFlowRate(data.getFlux()); // 瞬时流量
            dataHistory.setTension1(signalData.getTension1());
            dataHistory.setTension2(signalData.getTension2());
            dataHistory.setSignalinten(signalData.getSignallnten());
            historyService.insertWaterYcmeterDatahistory(dataHistory); // 添加历史数据
        }*/
        // 更新表具档案 实时数据
        waterMeter.setReadDate(latestData.getReadtime());
//        waterMeter.setInitialReading(waterMeter.getCurrentReading());
        waterMeter.setCurrentReading(latestData.getTotalFlux().toString());
        waterMeter.setPressure(latestData.getPressure().toString());
        waterMeter.setFlux(latestData.getFlux().toString());
        waterMeter.setSignalinten(signalData.getSignallnten()+"");
        return waterMeterService.updateWaterMeterNo(waterMeter);
    }

    /**
     * 流量压力数据推送接口
     */
    @Override
    public BaseResponse<FluxPressureData> getFluxPressureData(List<DeviceQuery> queries) {
        validateQueries(queries, 10, 300, "流量压力数据");

        String url = TaxConstants.BASEURL + "/data/datashare/flux";
        return executeRequest(url, queries, new TypeReference<BaseResponse<FluxPressureData>>() {});
    }

    /**
     * 电池电压与信号强度推送接口
     */
    @Override
    public BaseResponse<BatterySignalData> getBatterySignalData(List<DeviceQuery> queries) {
        validateQueries(queries, 20, 150, "电池电压信号强度");

        String url = TaxConstants.BASEURL + "/data/datashare/signallnten";
        return executeRequest(url, queries, new TypeReference<BaseResponse<BatterySignalData>>() {});
    }

    /**
     * 执行请求的通用方法
     */
    private <T> BaseResponse<T> executeRequest(String url, List<DeviceQuery> queries,
                                               TypeReference<BaseResponse<T>> typeReference) {
        // 频率控制
        controlAccessFrequency();

        try {
            // 准备请求参数
            BaseRequest request = new BaseRequest();
            request.setBody(queries);

            String requestBody = objectMapper.writeValueAsString(request);
            Map<String, Object> params = objectMapper.convertValue(request,
                    new TypeReference<Map<String, Object>>() {});

            // 生成签名
            long timestamp = System.currentTimeMillis();
            String signature = signatureUtil.generateSignature(
                    TaxConstants.APPID, TaxConstants.SECRETKEY, timestamp, params);

            // 准备请求头
            Map<String, String> headers = new HashMap<>();
            headers.put("appId", TaxConstants.APPID);
            headers.put("timestamp", String.valueOf(timestamp));
            headers.put("sign", signature);
            headers.put("Content-Type", "application/json; charset=utf-8");

            log.info("发送请求到: {}, 参数: {}", url, requestBody);

            // 发送请求
            String responseBody = httpClientUtil.post(url, requestBody, headers);

            log.info("收到响应: {}", responseBody);

            // 解析响应
            return objectMapper.readValue(responseBody, typeReference);

        } catch (Exception e) {
            log.error("调用拓安信接口失败", e);
            throw new RuntimeException("接口调用失败: " + e.getMessage(), e);
        }
    }

    /**
     * 验证查询参数
     */
    private void validateQueries(List<DeviceQuery> queries, int maxDevices, int maxNumber, String apiName) {
        if (queries == null || queries.isEmpty()) {
            throw new IllegalArgumentException(apiName + "查询参数不能为空");
        }

        if (queries.size() > maxDevices) {
            throw new IllegalArgumentException(apiName + "单次查询设备数量不能超过" + maxDevices);
        }

        for (DeviceQuery query : queries) {
            if (query.getNumber() > maxNumber) {
                throw new IllegalArgumentException(apiName + "单个设备查询条数不能超过" + maxNumber);
            }
        }
    }

    /**
     * 访问频率控制
     */
    private void controlAccessFrequency() {
        String appId = TaxConstants.APPID;
        long currentTime = System.currentTimeMillis();
        Long lastTime = lastAccessTime.get(appId);
        if (lastTime != null) {
            long interval = currentTime - lastTime;
            if (interval < MIN_INTERVAL) {
                try {
                    Thread.sleep(MIN_INTERVAL - interval);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }
        lastAccessTime.put(appId, System.currentTimeMillis());
    }

    /**
     * 处理错误码
     */
    @Override
    public void handleErrorCode(String code, String message) {
        switch (code) {
            case "0":
                return; // 成功
            case "110001":
                throw new RuntimeException("appId未在请求中");
            case "110002":
                throw new RuntimeException("签名未在请求中");
            case "110003":
                throw new RuntimeException("签名错误");
            case "110004":
                throw new RuntimeException("签名已过期");
            case "110005":
                throw new RuntimeException("非法的AppId");
            case "110008":
                throw new RuntimeException("仪表不存在: " + message);
            case "110009":
                throw new RuntimeException("单个仪表查询条数过大");
            case "110010":
                throw new RuntimeException("单次查询仪表数量过大");
            case "110011":
            case "110012":
                throw new RuntimeException("APPID已经被冻结");
            default:
                throw new RuntimeException("接口错误: " + code + " - " + message);
        }
    }
}
